/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.jbr.simplefoodplan.gwt.client.ui;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTMLTable.Cell;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.datepicker.client.CalendarUtil;
import com.jbr.simplefoodplan.gwt.client.Dish;
import com.jbr.simplefoodplan.gwt.client.MainEntryPoint;
import com.jbr.simplefoodplan.gwt.client.Plan;
import com.jbr.simplefoodplan.gwt.client.ServerCom;
import com.jbr.simplefoodplan.gwt.client.ServerCom.ElementCallback;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 *
 * @author jbr
 */
public final class PlanUi extends Composite {

    private static PlanUiUiBinder uiBinder = GWT.create(PlanUiUiBinder.class);

    private final MainEntryPoint main;
    private final Period period = new Period();

    public void updatePeriod() {
        startdate.setText(period.getStartDateFormatted());
        enddate.setText(period.getEndDateFormatted());
    }

    public void updateListBoxes() {
        for (int row = 0; row  < table.getRowCount(); row ++) {
            final ListBox listbox = (ListBox) table.getWidget(row, 2);
            listbox.clear();
            updateListBoxWithDishes(listbox);
            
        }
    }

    private void updateListBoxWithDishes(final ListBox listBox) {
        listBox.addItem("Ingen plan", "none");
        for (Dish dish : main.dishList) {
            String lastUsageInDays = dish.getLastUsageInDays();
            if (lastUsageInDays == null) {
                lastUsageInDays = "ikke brugt";
            }
            listBox.addItem(dish.getName() + " (" + lastUsageInDays + ")", dish.getId());
        }
        //listBox.addItem("Ny..", "new");
        //listBox.addItem("Fjern dag", "remove");
        //listBox.setSelectedIndex(main.dishList.indexOf(plan.getDish()));
        //listBox.addItem("Ny..", "new");
        //listBox.addItem("Fjern dag", "remove");
        //listBox.setSelectedIndex(main.dishList.indexOf(plan.getDish()));
    }

    interface PlanUiUiBinder extends UiBinder<Widget, PlanUi> {
    }

    @UiField FlexTable table;
    @UiField InlineHTML startdate;
    @UiField InlineHTML enddate;
    @UiField Button dishesMenu;
    @UiField Button next;
    @UiField Button previous;
    @UiField Button logout;


    public PlanUi(final MainEntryPoint main) {
        this.main = main;
        initWidget(uiBinder.createAndBindUi(this));
        table.setText(0,0,"");
        updatePeriod();
        updatePlanTable();
        next.setText(">>");
        next.setTitle("En uge frem");
        previous.setText("<<");
        previous.setTitle("En uger tilbage");
        dishesMenu.setText("Retter");
        dishesMenu.addClickHandler(new ClickHandler() {

            @Override
            public void onClick(ClickEvent event) {
                System.out.println("On click event for dishes");
                DishUi dishUi = new DishUi(main);
                dishUi.show();
                
            }
        });

        ServerCom.getLogoutUrl(new ServerCom.StringCallback() {

            @Override
            public void onResponseOk(final String string) {
                logout.setVisible(true);
                logout.setText("Log af");
                logout.addClickHandler(new ClickHandler() {

                    @Override
                    public void onClick(ClickEvent event) {
                        Window.Location.assign(string);
                    }
                });
            }
        });
    }
    private int indexOfDishId(List<Dish> dishList, Dish dishChosen) {
        int i=0;
        for (Dish dish : dishList) {
            if (dish.getId().equals(dishChosen.getId()))
                return i;
            i++;
        }
        return -1;
    }

    private ListBox getDishListBox(final int rowIndex, 
            final int cellIndex) {
        final Date date = period.getDatesInPeriod().get(rowIndex);
        System.out.println("Get dishListBox at " + MainEntryPoint.dateFormat.format(date));
        final ListBox listBox = new ListBox();
        listBox.setVisibleItemCount(1);
        updateListBoxWithDishes(listBox);
        //listBox.addItem("Ny..", "new");
        //listBox.addItem("Fjern dag", "remove");
        //listBox.setSelectedIndex(main.dishList.indexOf(plan.getDish()));
        
        main.getPlanAtDate(rowIndex, date,
                new ServerCom.ElementCallback<Plan, Integer>() {
            public void onResponseOk(Plan element, Integer backref) {
                System.out.println("For " + MainEntryPoint.dateFormat.format(date) +
                        " is " + element.getDish().getName() + " chosen.");
                listBox.setSelectedIndex(indexOfDishId(main.dishList, element.getDish())+1);
            }
        });

        listBox.addBlurHandler(new BlurHandler() {

            @Override
            public void onBlur(BlurEvent event) {
                //table.clearCell(rowIndex, cellIndex);
                //updateDishInPlan(listBox.getValue(listBox.getSelectedIndex()), plan);
                //updatePlanTable();

                listBox.setVisible(false);
                //System.out.println("Blur " + listBox.getValue(listBox.getSelectedIndex()));
            }
        });

        listBox.addChangeHandler(new ChangeHandler() {

            public void onChange(ChangeEvent event) {
                try {
                    final String selectedValue = listBox.getValue(listBox.getSelectedIndex());
                    if (selectedValue.equals("none")) {
                    }
                    final Long dishId = new Long(selectedValue);
                    final String name = "dishlistbox changed " + listBox.getValue(listBox.getSelectedIndex());
                    System.out.println(name);
                    final Date date = period.getDatesInPeriod().get(rowIndex);
                    JSONObject o = new JSONObject();
                    main.getPlanAtDate(rowIndex, date, new ElementCallback<Plan, Integer>() {

                        @Override
                        public void onResponseOk(Plan plan, Integer backref) {
                            if (plan == null) {
                                System.out.println("No plan found at date. Adding new plan");
                                plan = (Plan)JavaScriptObject.createObject();
                                plan.setRawDate(MainEntryPoint.jsonFormat.format(date));
                            } else
                                System.out.println("Plan id " + plan.getId() + " was edited ");

                            plan.setDishId(dishId.toString());
                            ServerCom.add(rowIndex, plan, new ServerCom.ElementCallback<Plan, Integer>() {

                                @Override
                                public void onResponseOk(Plan element, Integer backref) {
                                    table.setText(backref, 1, element.getDish().getName());
                                    main.addPlanInCache(element);
                                    System.out.println("Response ok. Plan added");

                                }
                            });

                        }
                    });


                } catch (NumberFormatException e) {
                    System.out.println("Der blev valgt noget uden nummer");
                }

            }
        });

        return listBox;
    }


    @UiHandler("next")
    void nextDay(ClickEvent e) {
        period.addDaysToEndDate(7);
        period.addDaysToStartDate(7);
        updatePeriod();
        updatePlanTable();
    }
    @UiHandler("previous")
    void previousDay(ClickEvent e) {
        period.addDaysToStartDate(-7);
        period.addDaysToEndDate(-7);
        updatePeriod();
        updatePlanTable();
    }

    public void updatePlanTable() {
        table.removeAllRows();
        int i = 0;
        for (final Date date : period.getDatesInPeriod()) {
            table.setText(i, 0, MainEntryPoint.dateFormat.format(date));
            table.getCellFormatter().setAlignment(i, 0, HasHorizontalAlignment.ALIGN_RIGHT, HasVerticalAlignment.ALIGN_MIDDLE);
            table.getCellFormatter().setWidth(i, 0, "200px");
            table.getCellFormatter().addStyleName(i, 0, "plan");
            table.getCellFormatter().addStyleName(i, 1, "plan");
            if (i%2==0) {
                table.getCellFormatter().addStyleName(i, 0, "plan-dark");
                table.getCellFormatter().addStyleName(i, 1, "plan-dark");
            }
            table.setText(i, 1, "(venter på server)");
            main.getPlanAtDate(new Integer(i), date, new ServerCom.ElementCallback<Plan, Integer>() {
                public void onResponseOk(Plan element, Integer backref) {
                    if (element == null)
                        table.setText(backref, 1, "Ingen plan");
                    else
                        table.setText(backref, 1, element.getDish().getName());

                    System.out.println(element.getDate() + " " + element.getDish().getName());
                }
            });
            
            i++;
        }
        table.addClickHandler(new ClickHandler() {

            public void onClick(ClickEvent event) {
                Cell cell = table.getCellForEvent(event);
                System.out.println("Clicked cell row:" + cell.getRowIndex() + " cell:" + cell.getCellIndex());

                // If the widget is allready set, then dont set it again
                // ClickEvent is fired on windows and ipad when clicking on the
                // Listbox, so it will reload the box making it imposible to
                // select anything
                if (cell != null && cell.getCellIndex() == 1 &&
                        table.getWidget(cell.getRowIndex(), cell.getCellIndex()) == null) {
                    table.setWidget(cell.getRowIndex(),
                            cell.getCellIndex(),
                            getDishListBox(
                                cell.getRowIndex(),
                                cell.getCellIndex()));
                }
            }
        });
    }

    private static class Period {

        Date startDate;
        Date endDate;

        public Period(Date startDate, Date endDate) {
            this.startDate = startDate;
            this.endDate = endDate;
        }

        public List<Date> getDatesInPeriod() {
            List<Date> list = new ArrayList<Date>();
            if (endDate.before(startDate))
                return list;
            Date curDate = CalendarUtil.copyDate(startDate);
            while (endDate.compareTo(curDate)>=0) {
                list.add(CalendarUtil.copyDate(curDate));
                CalendarUtil.addDaysToDate(curDate, 1);
            }
            return list;
        }

        public Period() {
            startDate = new Date();
            endDate = new Date();
            CalendarUtil.addDaysToDate(startDate, -7);
            CalendarUtil.addDaysToDate(endDate, 7);
        }

        public void addDaysToStartDate(int days) {
            System.out.println("old startdate is " + getStartDateFormatted());
            CalendarUtil.addDaysToDate(startDate, days);
            System.out.println("new startdate is " + getStartDateFormatted());
        }

        public void addDaysToEndDate(int days) {
            System.out.println("Old enddate is " + getEndDateFormatted());
            System.out.println("Old startdate is " + getStartDateFormatted());
            CalendarUtil.addDaysToDate(endDate, days);
            System.out.println("New enddate is " + getEndDateFormatted());
            System.out.println("New startdate is " + getStartDateFormatted());
        }

        public String getStartDateFormatted() {
            return MainEntryPoint.dateFormat.format(startDate);
        }

        public String getEndDateFormatted() {
            return MainEntryPoint.dateFormat.format(endDate);
        }

    }

}